package textchorus.sparql;

import java.util.*;

import textchorus.PSketch;
import textchorus.sparql.SparqlQuery.Tag;

public class WikiWalker {
	private PSketch p;
	private static int maxHops;
	private int hop;
	private Vector<SparqlQuery> walks;
	private Map<Tag, String> startq;

	public WikiWalker(PSketch p, int maxHops,Map<Tag, String> startq) {
		this.p = p;
		this.startq = startq;
		WikiWalker.maxHops = maxHops-1;
		hop = 0;

		walks = new Vector<SparqlQuery>();
		
//		SELECT ?s WHERE {?s <http://www.w3.org/2004/02/skos/core#subject> <http://dbpedia.org/resource/Category:Atheism>}
	}
	
	
	public static Map<Tag, String> makeQuery(Tag type, String res, Map<Tag, String> q) {
		if(q==null) {
			Map<Tag, String> newq = new HashMap<Tag, String>();
			newq.put(type, res);
			return newq;
		} else {
			q.put(type, res);
			return q;
		}
	}


	public boolean doNextHop() {
		if(hop>maxHops)
			return false;
		
//		System.out.println("[HOP: "+hop+"]");
		if(hop%2==0) {
			if(hop==0) {
				try {
					processQuery(startq);
				} catch (IndexOutOfBoundsException e) {
					System.out.println("no articles found!");
				}
			} else {
				// grab something else from the previous query's content
//				System.out.println("EVEN: Attempting to get next walk...");
				if(walks.size()>0) 
					preprocessHop();
			}
		} else {
			// grab branch from disambiguations/subjects to keep on walking; this will
			// have to be a two-step process as the proper category needs to be derived first
//			System.out.println("Attempting to get subjects...");
			
			if(walks.size()>0)
				preprocessHop();			
		}
		
//		Map<Tag, String> q = makeQuery(Tag.O, startNode, null);		
//		q = makeQuery(SparqlQuery.Tag.P, "<http://dbpedia.org/property/abstract>",q);
		
//		Map<Tag, String> qq = makeQuery(Tag.P, "http://dbpedia.org/property/occupation", null);		
//		qq = makeQuery(Tag.O, "http://dbpedia.org/resource/Poet", qq);		
//		SparqlQuery sqq = new SparqlQuery(qq);
		
		hop++;
		return true;
	}

	private void preprocessHop() {
		Map<Tag, String> q;
		
		SparqlQuery prevq = walks.get(hop-1);
		SparqlQuery tq;
		Vector<String> pSubs = prevq.getSubjects();
		
		if(pSubs.size()>0) {	// subjects
			Random r = new Random();
			int rIndex = r.nextInt(pSubs.size());
			
			String res = (String) pSubs.get(rIndex);
			
			q = makeQuery(Tag.O, res, null);
			q = makeQuery(Tag.P, "http://www.w3.org/2004/02/skos/core#subject", q);
			
			tq = new SparqlQuery(q);								
			Vector<String> tArticles = tq.getArticles();

			if(tArticles.size()>0) {
				Random r2 = new Random();
				int rIndex2 = r2.nextInt(tArticles.size());
				
				q = makeQuery(Tag.S, tArticles.get(rIndex2), null);
				
				try {
					processQuery(q);	
				} catch (IndexOutOfBoundsException e) {
					System.out.println("no branches found");
				}
			}		
							
		} else {				// disambiguations
			
			System.out.println("disambiguations");
			
			Vector<String> pDis = prevq.getDisambiguations();

			if(pDis.size()>0) {
				Random r = new Random();
				int rIndex = r.nextInt(pDis.size());
				
//				String res = (String) pSubs.get(rIndex);
				
				q = makeQuery(Tag.S, pDis.get(rIndex), null);				
				
				try {
					processQuery(q);	
				} catch (IndexOutOfBoundsException e) {
					System.out.println("no branches found");
				}
			}
		}
	}

	private void processQuery(Map<Tag, String> q) {
		SparqlQuery sq = new SparqlQuery(q);
		
		if(hop==0 && !q.containsKey(Tag.S)) {
			Vector<String> startArticles = sq.getArticles();
			
			int arrSize = startArticles.size();
			
			if(arrSize==0)
				throw new IndexOutOfBoundsException();

			System.out.println(startArticles.size());
			Random r = new Random();
			int rIndex = r.nextInt(startArticles.size());
			
			Map<Tag, String> newq = makeQuery(Tag.S, startArticles.get(rIndex),null);
			
			try {
				processQuery(newq);
			} catch (IndexOutOfBoundsException e) {
				System.out.println("no branches found");
			}
			
		} else {			
			// done with processing, now send abstract over to ChordMaker for analysis
			walks.add(sq);
			
			// send this out to audio generator
			p.cm.prepChorus(sq);
			
		}
	}

	public SparqlQuery getWalk() {
		System.out.println("######: " + walks.size());
		return null;
//		return walks.get(walks.size()-1);
	}
	
	public SparqlQuery getWalk(int idx) {		
		return walks.get(idx);		
	}
	
}
